package com.lsismo.core.base.dao.hibernate;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.lsismo.core.base.dao.GenericDao;
/**
 * 该类作为所有其他DAO的基类，也就是包含了所有可能用到的通用的CRUD方法，如果需要自定义CRUD逻辑，只需要继承该类
 *
 * <p>在Spring中注册该类，请参考使用如下XML
 * <pre>
 *      &lt;bean id="fooDao" class="com.dhcc.itsm.core.dao.hibernate.GenericDaoHibernate"&gt;
 *          &lt;constructor-arg value="com.dhcc.itsm.core.model.Foo"/&gt;
 *          &lt;property name="sessionFactory" ref="sessionFactory"/&gt;
 *      &lt;/bean&gt;
 * </pre>
 *
 * @param <T> 类型变量
 * @param <PK> 类型主键
 */
public class GenericDaoHibernate<T, PK extends Serializable> extends HibernateDaoSupport implements GenericDao<T, PK> {
    /**
     * 作用于所有子类的Log变量
     */
    protected final Log log = LogFactory.getLog(getClass());
    private Class<T> persistentClass;

    /**
     * 构造函数
     * @param persistentClass 要持久化的类
     */
    public GenericDaoHibernate(final Class<T> persistentClass) {
        this.persistentClass = persistentClass;
    }

    public Session getCurrentSession(){
    	return this.getSession();
    }
    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public List<T> getAll() {
        return super.getHibernateTemplate().loadAll(this.persistentClass);
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public T get(PK id) {
        T entity = (T) super.getHibernateTemplate().get(this.persistentClass, id);
        
        if (entity == null) {
            log.warn("Uh oh, '" + this.persistentClass + "' object with id '" + id + "' not found...");
            throw new ObjectRetrievalFailureException(this.persistentClass, id);
        }

        return entity;
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public boolean exists(PK id) {
        T entity = (T) super.getHibernateTemplate().get(this.persistentClass, id);
        return entity != null;
    }
    
    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public T save(T object) {
    	HibernateTemplate tmp= super.getHibernateTemplate();
    	tmp.setFlushMode(HibernateTemplate.FLUSH_AUTO);
        return (T) tmp.merge(object);
    }
    
    /**
     * {@inheritDoc}
     */
    public int bulkUpdate(String hql ,Object ... value){
    	
    	int successResult = 0;
    	if(value!=null&&value.length>0){
    		successResult = super.getHibernateTemplate().bulkUpdate(hql,value);
    	}else{
    		successResult = super.getHibernateTemplate().bulkUpdate(hql);
    	}
    	return successResult;
    }
    
    
    /**
     * {@inheritDoc}
     */
    public void remove(PK id) {
    	
        super.getHibernateTemplate().delete(this.get(id));
    }
    
    /**
     * {@inheritDoc}
     */
    public void remove(T object) {
    	super.getHibernateTemplate().delete(object);
	}

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unused")
    public void remove(PK ids , String idName ){
    	
		StringBuffer where = new StringBuffer();
		String[] arr = null;
		
		where.append(" where ").append(idName).append(" in ").append("( ");
		arr =  ((String)ids).split(",");
	    for (int i = 0; i < arr.length; i++)where.append(i>0?",":"").append("\'").append(arr[i]).append("\'");
    	where.append(" )");
    	
    	super.getHibernateTemplate()
    	     .bulkUpdate("delete from "+persistentClass.getSimpleName()+where.toString());
    }
    
    /**
     * {@inheritDoc}
     */
    public void bulkRemove(final PK[] ids) {
    	final String queryString = "delete " + persistentClass.getName() + " as model where model.id in (:ids) ";
        super.getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = session.createQuery(queryString);
                query.setParameterList("ids", ids);
                return query.executeUpdate();
            }
        });

    }
    
    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
	public List<T> findByExample(T instance)  {
    	return super.getHibernateTemplate().findByExample(instance);
    }
    
    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public List<T> findByProperty(String propertyName, Object value)  {
    	String queryString = "from " + persistentClass.getName() + " as model where model." + propertyName + "= ?";
    	return (List<T>)getHibernateTemplate().find(queryString, value);
    }
    
    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
	public List find(String hql, Object...values)  {
    	if(values!=null&&values.length>0)
    		return super.getHibernateTemplate().find(hql, values);
    	else
    		return super.getHibernateTemplate().find(hql);
    }
    
    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public List<T> getAllDistinct() {
        Collection result = new LinkedHashSet(getAll());
        return new ArrayList(result);
    }
	
    /**
     * {@inheritDoc}
     */
	@SuppressWarnings("unchecked")
	public List<T> findByNamedQuery(String queryName, Map<String, Object> queryParams)throws Exception {
       String []params = new String[queryParams.size()];
       Object []values = new Object[queryParams.size()];
       int index = 0;
       Iterator<String> i = queryParams.keySet().iterator();
       while (i.hasNext()) {
           String key = i.next();
           params[index] = key;
           values[index++] = queryParams.get(key);
       }
       return getHibernateTemplate().findByNamedQueryAndNamedParam(
           queryName, 
           params, 
           values);
    }
	
	/**
     * {@inheritDoc}
     */
	@SuppressWarnings({ "deprecation", "unchecked" })
	public List<T> findPageAll(final String hql,final int first,final int max) throws Exception {
		return  (List<T>) super.getHibernateTemplate().executeFind(new HibernateCallback(){
			  public Object doInHibernate(Session session)
			  throws HibernateException, SQLException {
				  Query query = session.createQuery(hql);
				  return query.setFirstResult(first).setMaxResults(max).list();
			}
		});
	}
	
	/**
     * {@inheritDoc}
     */
	public int getInfosCount(String hqlQuery)throws Exception {
		if(hqlQuery.contains("order by")){
			hqlQuery = hqlQuery.substring(0,hqlQuery.indexOf("order by"));
		}
		
		StringBuilder sb = new StringBuilder("select count(*) ");
		String lowerStr = hqlQuery.toLowerCase();
		if(lowerStr.trim().startsWith("select")){
			String fromHql = hqlQuery.substring(hqlQuery.indexOf("from")+4,hqlQuery.length());
			sb.append("from ").append(fromHql).append(" ");
		}else if(lowerStr.trim().startsWith("from")){
			sb.append(hqlQuery.trim());
		}
		Session  session = getSession();
	    Query query = session.createQuery(sb.toString());
	    int lo=0;
	    try {
	    	System.out.println("ssss");
	    	 lo= ((Long)query.iterate().next()).intValue();
	    	 System.out.println(lo);
		} catch (Exception e) {
			System.out.println("fff");
           e.printStackTrace();
		}
		return lo;
	}

	@SuppressWarnings("unchecked")
	public List<T> findPageAll(final String hql, final int first,
			final int max, final Object... values) throws Exception {
		return (List<T>) super.getHibernateTemplate().executeFind(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(hql);
						for (int i = 0; i < values.length; i++) {
							query.setParameter(i, values[i]);
//							if (values[i] instanceof Integer) {
//								query.setInteger(i, (Integer) values[i]);
//							} else if (values[i] instanceof String) {
//								query.setString(i, (String) values[i]);
//							} else if (values[i] instanceof Double) {
//								query.setDouble(i, (Double) values[i]);
//							}
						}
						return query.setFirstResult(first).setMaxResults(max)
								.list();
					}
				});
	}

	public int getInfosCount(String hqlQuery, Object... values)
			throws Exception {
		if(hqlQuery.contains("order by")){
			hqlQuery = hqlQuery.substring(0,hqlQuery.indexOf("order by"));
		}
		StringBuilder sb = new StringBuilder("select count(*) ");
		String lowerStr = hqlQuery.toLowerCase();
		if(lowerStr.trim().startsWith("select")){
			String fromHql = hqlQuery.substring(hqlQuery.indexOf("from")+4,hqlQuery.length());
			sb.append("from ").append(fromHql).append(" ");
		}else if(lowerStr.trim().startsWith("from")){
			sb.append(hqlQuery.trim());
		}
		Session  session = getSession();
	    Query query = session.createQuery(sb.toString());
	    for (int i = 0; i < values.length; i++) {
	    	query.setParameter(i, values[i]);
//	    	if (values[i] instanceof Integer) {
//				query.setInteger(i, (Integer) values[i]);
//			} else if (values[i] instanceof String) {
//				query.setString(i, (String) values[i]);
//			} else if (values[i] instanceof Double) {
//				query.setDouble(i, (Double) values[i]);
//			}
		}
		return ((Long)query.iterate().next()).intValue();
	}
	 /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public Object commonFindById(Class clazz, PK id) {
     
    	Object entity = super.getHibernateTemplate().get(clazz, id);
  
    	if (entity == null) {
    		log.warn("Uh oh, &apos;" + this.persistentClass + "&apos; object with id &apos;" + id + "&apos; not found...");
    		throw new ObjectRetrievalFailureException(this.persistentClass, id);
    	}
     
    	return entity;
    }
 
}
